package com.gambi.example.client.chatter.control;

import java.util.List;

import com.gambi.example.client.chatter.events.SendMessageEvent;
import com.gambi.example.client.chatter.events.SignOffEvent;
import com.gambi.example.client.chatter.events.SignOnEvent;
import com.gambi.example.client.chatter.model.Contact;
import com.gambi.example.client.chatter.model.ContactList;
import com.gambi.example.client.chatter.model.Message;
import com.gambi.example.client.chatter.services.MessengerService;
import com.gambi.example.client.chatter.services.MessengerServiceAsync;
import com.gambi.example.client.chatter.view.MessengerView;
import com.gambi.example.client.chatter.view.MessengerViewListener;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.Dictionary;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

public class MessengerServiceClientImpl implements MessengerViewListener {
	private MessengerServiceAsync messengerService;
	private ContactList contactList;
	private MessengerView view = new MessengerView(this);
	private Dictionary dictionary;

	public MessengerServiceClientImpl(Dictionary dictionary) {
		this.dictionary = dictionary;
		messengerService = (MessengerServiceAsync) GWT
				.create(MessengerService.class);
	}

	public MessengerView getView() {
		return view;
	}

	public void onSignIn(String name) {
		((ServiceDefTarget) messengerService).setServiceEntryPoint(dictionary
				.get("signineventlink"));
		contactList = new ContactList(name);
		GWT.log("MessengerServiceClientImpl.onSignIn() " + name);
		messengerService.signIn(name, new SignInCallback());
	}

	public void onSignOut() {
		view.signOut();
		((ServiceDefTarget) messengerService).setServiceEntryPoint(dictionary
				.get("signouteventlink"));
		messengerService.signOut(new SignOutCallback());
	}

	public void onSendMessage(Contact toContact, Message message) {
		((ServiceDefTarget) messengerService).setServiceEntryPoint(dictionary
				.get("sendmessageeventlink"));
		messengerService.sendMessage(toContact, message, new EmptyCallback());
	}

	protected void handleEvent(Object event) {
		if (event instanceof SendMessageEvent) {
			SendMessageEvent sendMessageEvent = (SendMessageEvent) event;
			view.getChatWindowView(sendMessageEvent.sender).addMessage(
					sendMessageEvent.message);
		} else if (event instanceof SignOnEvent) {
			SignOnEvent signOnEvent = (SignOnEvent) event;
			view.getContactListView().addContact(signOnEvent.contact);
		} else if (event instanceof SignOffEvent) {
			SignOffEvent signOffEvent = (SignOffEvent) event;
			if (view.getContactList().getMe().equals(signOffEvent.contact)) {
				// Skip this ;)
			} else {
				view.getContactListView().removeContact(signOffEvent.contact);
			}
		}
	}

	private class SignInCallback implements AsyncCallback {
		public void onFailure(Throwable throwable) {
			GWT.log("error sign in", throwable);
		}

		public void onSuccess(Object obj) {
			GWT.log("MessengerServiceClientImpl.SignInCallback.onSuccess() "
					+ contactList);
			view.setContactList(contactList);
			// For Event-Based communication

			((ServiceDefTarget) messengerService)
					.setServiceEntryPoint(dictionary.get("geteventseventlink"));
			messengerService.getEvents(new GetEventsCallback());
		}
	}

	private class SignOutCallback implements AsyncCallback {
		public void onFailure(Throwable throwable) {
			GWT.log("error sign out", throwable);
		}

		public void onSuccess(Object obj) {
			GWT.log("MessengerServiceClientImpl.SignOutCallback.onSuccess() ");
			view.reset();
		}
	}

	private class EmptyCallback implements AsyncCallback {
		public void onFailure(Throwable throwable) {
			GWT.log("error", throwable);
		}

		public void onSuccess(Object obj) {
		}
	}

	private class GetEventsCallback implements AsyncCallback {
		public void onFailure(Throwable throwable) {
			GWT.log("error get events", throwable);
		}

		public void onSuccess(Object obj) {
			List events = (List) obj;
			boolean continuteGetEvents = true;
			for (int i = 0; i < events.size(); ++i) {
				Object event = events.get(i);
				handleEvent(event);
				if (event instanceof SignOffEvent) {
					GWT.log("Sign out : "
							+ ((SignOffEvent) event).contact.getName());
					GWT.log("Me : " + view.getContactList().getMe().getName());
					if (((SignOffEvent) event).contact.equals(view
							.getContactList().getMe())) {
						continuteGetEvents = false;
					}
				}
			}

			if (!continuteGetEvents) {
				return;
			}

			((ServiceDefTarget) messengerService)
					.setServiceEntryPoint(dictionary.get("geteventseventlink"));
			messengerService.getEvents(this);
		}
	}
}
